package controller

import (
	"../model/dto"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/websocket"
	"set"
	"strconv"
	"sync"
)

var clientMap map[int64]*Target = make(map[int64]*Target, 0)

// 读写锁
var rwLocker sync.RWMutex

type Target struct {
	Connection   *websocket.Conn
	MessageQueue chan []byte
	GroupSet     set.Interface
}

/**
 * websocket 方法, ws://...
 */
func Chat(writer http.ResponseWriter, request *http.Request) {

	queryParams := request.URL.Query()
	id := queryParams.Get("id")
	// token := queryParams.Get("token")

	userId, _ := strconv.ParseInt(id, 10, 64)

	// 暂时没有验证token
	connection, err := (&websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}).Upgrade(writer, request, nil)
	if err != nil {
		log.Println(err.Error())
		return
	}

	target := &Target{
		Connection:   connection,
		MessageQueue: make(chan []byte, 50),
		GroupSet:     set.New(set.ThreadSafe),
	}

	rwLocker.Lock()
	clientMap[userId] = target
	rwLocker.Unlock()
	log.Printf("%d 成功建立连接", userId)

	go sendProc(target)
	go recvProc(target)
}

func sendProc(target *Target) {

	for {
		select {
		case data := <-target.MessageQueue:
			err := target.Connection.WriteMessage(websocket.TextMessage, data)
			if err != nil {
				log.Println(err.Error())
				return
			}
		}
	}
}

func recvProc(target *Target) {

	for {

		_, data, err := target.Connection.ReadMessage()
		if err != nil {
			log.Println(err.Error())
			return
		}

		fmt.Println(string(data))
		dispatch(data)
	}
}

/**
 * 流转数据，将收到的信息发送给指定用户
 */
func dispatch(data []byte) {

	message := dto.Message{}
	err := json.Unmarshal(data, &message)
	if err != nil {
		log.Println(err.Error())
		return
	}

	targetId, _ := strconv.ParseInt(message.ReceiverId, 10, 64)
	// 发送消息
	SendMessage(targetId, []byte(message.Content))
}

func SendMessage(targetId int64, message []byte) {

	rwLocker.RLock()
	target, isOK := clientMap[targetId]
	rwLocker.RUnlock()
	if isOK {
		// 将消息写入到channel，后续协程将自动发送消息
		target.MessageQueue <- message
	}
}
